/**
 * Project Name:OrgController
 * File Name:OrgController.java
 * Package Name:com.bwda.dsrs.systemservice.controller;
 * Date:2019年4月28日
 * Copyright (c) 2019, 江苏保旺达软件有限公司 All Rights Reserved.
 */
package com.bwda.dsrs.systemservice.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bwda.dsrs.base.centerbase.response.CentreCutPageResponse;
import com.bwda.dsrs.base.centerbase.response.CentreListResponse;
import com.bwda.dsrs.base.centerbase.response.ResponseEntity;
import com.bwda.dsrs.base.util.CopyUtil;
import com.bwda.dsrs.systemservice.annotations.NeedRole;
import com.bwda.dsrs.systemservice.annotations.WithDefaultAuth;
import com.bwda.dsrs.systemservice.aspect.LogTypeEnum;
import com.bwda.dsrs.systemservice.aspect.Loggable;
import com.bwda.dsrs.systemservice.domain.Constants;
import com.bwda.dsrs.systemservice.domain.condition.org.OrgCondition;
import com.bwda.dsrs.systemservice.domain.exception.SystemServiceException;
import com.bwda.dsrs.systemservice.domain.form.org.*;
import com.bwda.dsrs.systemservice.domain.form.user.UserForm;
import com.bwda.dsrs.systemservice.domain.po.group.GroupPo;
import com.bwda.dsrs.systemservice.domain.po.org.OrgPo;
import com.bwda.dsrs.systemservice.domain.po.user.UserPo;
import com.bwda.dsrs.systemservice.domain.vo.org.CustomOrgUserTreeVo;
import com.bwda.dsrs.systemservice.domain.vo.org.OrgUserSelectVo;
import com.bwda.dsrs.systemservice.domain.vo.org.OrgVo;
import com.bwda.dsrs.systemservice.service.GroupService;
import com.bwda.dsrs.systemservice.service.OrgService;
import com.bwda.dsrs.systemservice.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 组织菜单管理类
 *
 * @author youzhen
 * @date 2019年4月28日
 */
@RestController
@RequestMapping("/s/org")
@Api(value = "/s/org", tags = "组织表")
public class OrgController extends BaseController {

    @Autowired
    private OrgService orgService;
    @Autowired
    private UserService userService;
    @Autowired
    private GroupService groupService;

    @ApiOperation(value = "查询组织表", notes = "查询组织表", httpMethod = "GET")
    @Loggable(descp = "查询组织表", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/query", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<OrgVo> query(@ApiParam(value = "ID", required = true) @RequestParam Integer id) throws SystemServiceException {
        OrgPo po = orgService.queryWithValid(id);
        OrgVo vo = CopyUtil.transfer(po, OrgVo.class);
        return getSuccessResult(vo);
    }

    @ApiOperation(value = "查询组织表数量", notes = "查询组织表数量", httpMethod = "GET")
    @Loggable(descp = "查询组织表数量", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryCount", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<Integer> queryCount(@ModelAttribute @Valid OrgQueryForm form) throws SystemServiceException {
        OrgCondition condition = this.getConditionByQueryForm(form);
        int count = orgService.queryCount(condition);
        return getSuccessResult(count);
    }

    @ApiOperation(value = "查询组织树", notes = "查询组织树", httpMethod = "POST")
    @Loggable(descp = "查询组织树", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryTree", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<List<OrgTreeForm>> queryTree() throws SystemServiceException {
        List<OrgTreeForm> poList = orgService.queryTreeList(new OrgTreeForm());
        List<OrgTreeForm> treeList = orgService.queryTree(poList);
        return getSuccessResult(treeList);
    }

    @ApiOperation(value = "查询组织树节点", notes = "查询组织树节点", httpMethod = "GET")
    @Loggable(descp = "查询组织树节点", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryTreeChildren", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<List<OrgTreeForm>> queryTreeChildren(@ApiParam(value = "id", required = true) @RequestParam Integer id) throws SystemServiceException {
        List<OrgTreeForm> poList = orgService.queryTreeChildren(id);
        return getSuccessResult(poList);
    }

    @ApiOperation(value = "查询组织表列表", notes = "查询组织表列表", httpMethod = "GET")
    @Loggable(descp = "查询组织表列表", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryList", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<CentreListResponse<OrgTreeForm>> queryList(@ModelAttribute @Valid OrgTreeForm form) throws SystemServiceException {
        List<OrgTreeForm> poList = orgService.queryOrgList(form);
        return getSuccessResult(getListResponse(poList));
    }

    @ApiOperation(value = "查询组织表列表(带分页)", notes = "查询组织表列表(带分页)", httpMethod = "GET")
    @Loggable(descp = "查询组织表列表(带分页)", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryPageList", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<CentreCutPageResponse<OrgVo>> queryPageList(@ModelAttribute @Valid OrgQueryForm form) throws SystemServiceException {
        OrgCondition condition = this.getConditionByQueryForm(form);
        List<OrgVo> voList = new ArrayList<>();

        // TODO 这边看不懂，这是查询接口，却查询的是子组织
        condition.setId(null);
        condition.setParentId(form.getId());
        int count = orgService.queryCount(condition);
        if (count > 0) {
            List<OrgPo> poList = orgService.queryList(condition);
            voList = CopyUtil.transfer(poList, OrgVo.class);
            appendOrgAdminNames(voList);
        }
        return getSuccessResult(getPageResponse(form, count, voList));
    }

    private void appendOrgAdminNames(List<OrgVo> voList) {
        //组织管理员查得不对，是可以多个的
        List<String> adminUserCodes = new ArrayList<>();
        voList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getOrgAdminCode())) {
                String[] tempCodes = item.getOrgAdminCode().split(",");
                for (String code : tempCodes) {
                    adminUserCodes.add(code);
                }
            }
        });

        if (CollectionUtils.isEmpty(adminUserCodes)) {
            return;
        }

        List<UserForm> userFormList = userService.queryUserByUserCodeList(adminUserCodes.toArray(new String[adminUserCodes.size()]));

        voList.forEach(item -> {
            StringBuilder names = new StringBuilder();
            if (StringUtils.isNotEmpty(item.getOrgAdminCode())) {
                String[] tempCodes = item.getOrgAdminCode().split(",");
                for (String code : tempCodes) {
                    if (StringUtils.isNotEmpty(names)) {
                        names = names.append("," + getNameByUserCode(userFormList, code));
                    } else {
                        names = names.append(getNameByUserCode(userFormList, code));
                    }

                }
            }
            //把最后一个逗号去掉

            item.setOrgAdminName(names.toString());
        });

    }

    /**
     * 这些信息最好缓存起来
     */
    private String getNameByUserCode(List<UserForm> userList, String userCode) {

        String name = "";
        for (UserForm userForm : userList) {
            if (userCode.equals(userForm.getUserCode())) {
                name = userForm.getUserName();
                break;
            }
        }

        return name;

    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "新增组织表", notes = "新增组织表", httpMethod = "POST")
    @Loggable(descp = "新增组织表", type = LogTypeEnum.CREATE, include = "")
    @RequestMapping(value = "/add", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<OrgVo> add(@ModelAttribute @Valid OrgCreateForm form, HttpServletRequest request) throws SystemServiceException {
        OrgPo po = CopyUtil.transfer(form, OrgPo.class);
        //修改组织不能重名
        OrgCondition orgCondition = new OrgCondition();
        orgCondition.setOrgName(form.getOrgName());
        orgCondition.setParentId(form.getParentId());
        List<OrgPo> poList = orgService.queryName(orgCondition);
        boolean hasRepeatedName = false;
        for (OrgPo org : poList) {
            //同组织下有无重复的名称、
            if (form.getOrgName().equals(org.getOrgName())) {
                hasRepeatedName = true;
                break;
            }
        }

        if (hasRepeatedName) {
            throw new SystemServiceException("组织名称重复");
        }
        //po.setOrgCode(UUIDUtil.getUuid());
        String creatUserCode = getUserCodeVal();
        if (Constants.TOKEN_ERROR.equals(creatUserCode)) {
            return getFailResult("token无效");
        }
        if ("".equals(form.getOrgAdminCode())) {
            po.setOrgAdminCode("sysadmin");
        }
        po.setCreateUserCode(creatUserCode);
        orgService.insert(po);
        OrgVo vo = CopyUtil.transfer(po, OrgVo.class);
        return getSuccessResult(vo);
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "修改组织表", notes = "修改组织表", httpMethod = "POST")
    @Loggable(descp = "修改组织表", type = LogTypeEnum.UPDATE, include = "")
    @RequestMapping(value = "/update", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity update(@ModelAttribute @Valid OrgUpdateForm form) throws SystemServiceException {
        //修改组织不能重名
        OrgCondition orgCondition = new OrgCondition();
        orgCondition.setOrgName(form.getOrgName());
        OrgPo po1 = orgService.query(form.getId());
        orgCondition.setParentId(po1.getParentId());
        List<OrgPo> poList = orgService.queryName(orgCondition);
        boolean hasRepeatedName = false;
        for (OrgPo org : poList) {
            //同组织下有无重复的名称、
            if (!form.getId().equals(org.getId()) && form.getOrgName().equals(org.getOrgName())) {
                hasRepeatedName = true;
                break;
            }
        }

        if (hasRepeatedName) {
            throw new SystemServiceException("组织名称重复");
        }


        OrgPo po = CopyUtil.transfer(form, OrgPo.class);
        orgService.update(po);
        return getSuccessResult();
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "删除组织表", notes = "删除组织表", httpMethod = "POST")
    @Loggable(descp = "删除组织表", type = LogTypeEnum.DELETE, include = "")
    @RequestMapping(value = "/delete", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity delete(@ApiParam(value = "ID", required = true) @RequestParam String ids) throws SystemServiceException {
        Map<String, String> map = orgService.deleteUserByIds(ids);
        //是否删除成功，true or flase;
        String state = map.get("state");
        String code = "false";
        if (code.equals(state)) {
            return getFailResult(map.get("msg"));
        } else {
            return getSuccessResult(map.get("msg"));
        }
    }

    @ApiOperation(value = "获取所有组织管理员", notes = "获取所有组织管理员", httpMethod = "POST")
    @Loggable(descp = "获取所有组织管理员", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryAdmin", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<List<OrgUserAdminForm>> queryAdmin() throws SystemServiceException {
        List<OrgUserAdminForm> list = orgService.queryAdmin();
        return getSuccessResult(list);
    }

    @ApiOperation(value = "获取组织ID管理员", notes = "获取组织ID管理员", httpMethod = "POST")
    @Loggable(descp = "获取组织ID管理员", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrgAdmin", method = {RequestMethod.GET, RequestMethod.POST})
    public List<OrgUserAdminForm> queryOrgAdmin(@ApiParam(value = "ID", required = true) @RequestParam Integer id) throws SystemServiceException {
        List<OrgUserAdminForm> list = orgService.queryOrgAdmin(id);
        return list;
    }

    @ApiOperation(value = "获取组织管理员", notes = "获取组织ID管理员", httpMethod = "POST")
    @Loggable(descp = "获取组织ID管理员", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrgAdminByUserCode", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<List<OrgUserAdminForm>> queryOrgAdminByUserCode() throws SystemServiceException {
        String userCode = getUserCode();
        OrgCreateForm org = orgService.queryOrg(userCode);
        List<OrgUserAdminForm> list = orgService.queryOrgAdmin(org.getId());
        //把自己删除
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            OrgUserAdminForm tempUser = (OrgUserAdminForm) iterator.next();
            if (userCode.equals(tempUser.getUserCode())) {
                iterator.remove();
            }
        }
        //万一他自己就是管理员，查一下上级，如果上级也没有就不管了。
        if (CollectionUtils.isEmpty(list) && org.getParentId() != null && org.getParentId() >= 0) {
            list.addAll(orgService.queryOrgAdmin(org.getParentId()));
        }

        return getSuccessResult(list);
    }

    @ApiOperation(value = "获取自定义组管理员", notes = "获取自定义组管理员", httpMethod = "POST")
    @Loggable(descp = "获取自定义组管理员", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryGroupAdmin", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<List<OrgUserAdminForm>> queryGroupAdmin(@ApiParam(value = "自定义组ID", required = true) @RequestParam Integer groupId) throws SystemServiceException {
        GroupPo groupPo = groupService.queryWithDetail(groupId);
        String adminUserCode = groupPo.getAdminUserCode();
        List<OrgUserAdminForm> list = new ArrayList<>();

        if (StringUtils.isNotEmpty(adminUserCode)) {
            String[] useCodes = adminUserCode.split(",");
            for (String useCode : useCodes) {
                List<UserForm> userForms = userService.queryUserByCode(useCode);
                OrgUserAdminForm adminForm = new OrgUserAdminForm();
                adminForm.setUserCode(useCode);
                adminForm.setUserName(userForms.get(0).getUserName());
                list.add(adminForm);
            }

        }
        return getSuccessResult(list);
    }

    @WithDefaultAuth
    @ApiOperation(value = "根据用户获得组织信息", notes = "根据用户获得组织信息", httpMethod = "POST")
    @Loggable(descp = "根据用户获得组织信息", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrg")
    public OrgCreateForm queryOrg(@RequestParam String userCode) throws SystemServiceException {
        OrgCreateForm org = orgService.queryOrg(userCode);
        return org;
    }

    @ApiOperation(value = "根据用户获得组织信息（返回类型ResponseEntity）", notes = "根据用户获得组织信息", httpMethod = "POST")
    @Loggable(descp = "根据用户获得组织信息", type = LogTypeEnum.QUERY, include = "")
    @PostMapping(value = "/querySystemOrg")
    public ResponseEntity<OrgCreateForm> querySystemOrg(@RequestParam String userCode) throws SystemServiceException {
        OrgCreateForm org = orgService.queryOrg(userCode);
        return getSuccessResult(org);
    }


    @ApiOperation(value = "获得组织信息", notes = "获得组织信息", httpMethod = "POST")
    @Loggable(descp = "获得组织信息", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryByIdOrg", method = {RequestMethod.GET, RequestMethod.POST})
    public OrgCreateForm queryByIdOrg(@ApiParam(value = "id", required = true) @RequestParam Integer id) throws SystemServiceException {
        OrgCreateForm org = orgService.queryByIdOrg(id);
        return org;
    }

    @ApiOperation(value = "查询人员组织树", notes = "查询人员组织树", httpMethod = "GET")
    @Loggable(descp = "查询人员组织树", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrgUserTree", method = {RequestMethod.GET, RequestMethod.POST})
    public List<OrgUserTreeForm> queryOrgUserTree() throws SystemServiceException {
        List<OrgUserTreeForm> poList = orgService.queryUserOrgList();
        List<OrgUserTreeForm> treeList = orgService.queryUserOrgTree(poList);
        return treeList;
    }

    @ApiOperation(value = "按级查询组织树", notes = "按级查询组织树", httpMethod = "GET")
    @Loggable(descp = "按级查询组织树", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrgSingleTree", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<List<OrgUserTreeForm>> queryOrgSingleTree(@RequestParam Integer id) throws SystemServiceException {
        List<OrgUserTreeForm> poList = orgService.queryOrgSingleTree(id);
        return getSuccessResult(poList);
    }

    @ApiOperation(value = "查询组织树", notes = "查询组织树", httpMethod = "GET")
    @Loggable(descp = "查询组织树", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrgTree", method = {RequestMethod.GET, RequestMethod.POST})
    public List<OrgTreeForm> queryOrgTree() throws SystemServiceException {
        List<OrgTreeForm> poList = orgService.queryTreeList(new OrgTreeForm());
        List<OrgTreeForm> treeList = orgService.queryTree(poList);
        return treeList;
    }

    @ApiOperation(value = "查询批量组织", notes = "查询批量组织", httpMethod = "GET")
    @Loggable(descp = "查询批量组织", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryOrgById", method = {RequestMethod.GET, RequestMethod.POST})
    public List<OrgCreateForm> queryOrgById(@ApiParam(value = "id", required = true) @RequestParam("ids") String ids) throws SystemServiceException {
        List<OrgCreateForm> poList = orgService.queryOrgById(ids);
        return poList;
    }

    @ApiOperation(value = "自定义查询人员组织树（自定义组,用户分级用）", notes = "查询人员组织树（自定义组,用户分级用）", httpMethod = "GET")
    @Loggable(descp = "自定义查询人员组织树", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryCustomOrgUserTree", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<CentreListResponse<OrgUserSelectVo>> queryCustomOrgUserTree() throws SystemServiceException {
        List<OrgUserTreeForm> poList = orgService.queryUserOrgList();
        List<OrgUserTreeForm> treeList = orgService.queryUserOrgTree(poList);
        List<CustomOrgUserTreeVo> userTreeVoList = new ArrayList<>();
        for (OrgUserTreeForm vo : treeList) {
            //deep copy
            CustomOrgUserTreeVo select = JSON.parseObject(JSON.toJSONString(vo), new TypeReference<CustomOrgUserTreeVo>() {
            });
            userTreeVoList.add(select);
        }
        filter(userTreeVoList);
        List<OrgUserSelectVo> targetList = new ArrayList<>();
        for (CustomOrgUserTreeVo vo : userTreeVoList) {
            //deep copy
            OrgUserSelectVo select = JSON.parseObject(JSON.toJSONString(vo), new TypeReference<OrgUserSelectVo>() {
            });
            targetList.add(select);
        }
        return getSuccessResult(getListResponse(targetList));
    }

    @ApiOperation(value = "根据UserCode获取所有上级组织（包括本组织）", notes = "根据UserCode获取所有上级组织（包括本组织）", httpMethod = "POST")
    @Loggable(descp = "根据UserCode获取所有上级组织（包括本组织）", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryParentOrgByUserCode", method = {RequestMethod.GET, RequestMethod.POST})
    public List<OrgCreateForm> queryParentOrgByUserCode(@RequestParam("userCode") String userCode) throws SystemServiceException {
        //先根据usercode 查询组织
        UserPo userPo = userService.queryUserByUserCode(userCode);
        List<OrgCreateForm> list = orgService.queryParentOrgByUserCode(userPo.getOrgId());
        return list;
    }

    /**
     * 树形结构字段转换
     *
     * @param list
     */
    private void filter(List<CustomOrgUserTreeVo> list) {
        if (list != null && list.size() > 0) {
            for (CustomOrgUserTreeVo form : list) {
                if (!Constants.OrgUserTree.USER_NODE_ID.equals(form.getId())) {
                    form.setUserCode(null);
                    form.setName(form.getOrgName());
                } else {
                    form.setName(form.getUserName());
                    form.setId(form.getUserCode());
                }
                if (form.getChildren() != null && form.getChildren().size() > 0) {
                    filter(form.getChildren());
                }
            }
        }
    }

    /**
     * OrgQueryForm转换为OrgCondition
     *
     * @param form
     * @return
     */
    private OrgCondition getConditionByQueryForm(OrgQueryForm form) {
        OrgCondition condition = CopyUtil.transfer(form, OrgCondition.class);
        return condition;
    }

    private String getUserCodeVal() throws SystemServiceException {
        String userCode = getUserCode();
        if (StringUtils.isBlank(userCode)) {
            logger.error("获取用户信息异常");
            return null;
        }
        return userCode;
    }
}